impl Work {
pub fn new<F>(f: F) -> Work
- where F: FnOnce(Sender<String>) -> CargoResult<()> + Send + 'static {
+ where F: FnOnce(Sender<String>) -> CargoResult<()> + Send + 'static
+ {
Work { inner: Box::new(f) }
}
impl Job {
/// Create a new job representing a unit of work.
- pub fn new(dirty: Work,
- fresh: Work) -> Job {
+ pub fn new(dirty: Work, fresh: Work) -> Job {
Job { dirty: dirty, fresh: fresh }
}
- /// Create a new job which will run `fresh` if the job is fresh and
- /// otherwise not run `dirty`.
- ///
- /// Retains the same signature as `new` for compatibility. This job does not
- /// describe itself to the console.
- pub fn noop(_dirty: Work,
- fresh: Work) -> Job {
- Job { dirty: Work::noop(), fresh: fresh }
- }
-
/// Consumes this job by running it, returning the result of the
/// computation.
pub fn run(self, fresh: Freshness, tx: Sender<String>) -> CargoResult<()> {
active: u32,
pending: HashMap<(&'a PackageId, Stage), PendingBuild>,
state: HashMap<&'a PackageId, Freshness>,
- ignored: HashSet<&'a PackageId>,
printed: HashSet<&'a PackageId>,
}
active: 0,
pending: HashMap::new(),
state: HashMap::new(),
- ignored: HashSet::new(),
printed: HashSet::new(),
}
}
(pkg, jobs));
}
- pub fn ignore(&mut self, pkg: &'a Package) {
- self.ignored.insert(pkg.package_id());
- }
-
/// Execute all jobs necessary to build the dependency graph.
///
/// This function will spawn off `config.jobs()` workers to build all of the
// In general, we try to print "Compiling" for the first nontrivial task
// run for a package, regardless of when that is. We then don't print
// out any more information for a package after we've printed it once.
- let print = !self.ignored.contains(&pkg.package_id());
- let print = print && !self.printed.contains(&pkg.package_id());
+ let print = !self.printed.contains(&pkg.package_id());
if print && (stage == Stage::Libraries ||
(total_fresh == Dirty && running.len() > 0)) {
self.printed.insert(pkg.package_id());
compiled.insert(dep.package_id().clone());
});
for dep in deps.iter() {
- if dep == pkg { continue }
+ if dep == pkg || !compiled.contains(dep.package_id()) { continue }
// Only compile lib targets for dependencies
let targets = dep.targets().iter().filter(|target| {
return Err(human(format!("Package `{}` has no library targets", dep)))
}
- let compiled = compiled.contains(dep.package_id());
- try!(compile(&targets, dep, compiled, &mut cx, &mut queue));
+ try!(compile(&targets, dep, &mut cx, &mut queue));
}
- try!(compile(targets, pkg, true, &mut cx, &mut queue));
+ try!(compile(targets, pkg, &mut cx, &mut queue));
// Now that we've figured out everything that we're going to do, do it!
try!(queue.execute(cx.config));
}
fn compile<'a, 'b>(targets: &[&'a Target], pkg: &'a Package,
- compiled: bool,
cx: &mut Context<'a, 'b>,
jobs: &mut JobQueue<'a>) -> CargoResult<()> {
debug!("compile_pkg; pkg={}", pkg);
let _p = profile::start(format!("preparing: {}", pkg));
- // Packages/targets which are actually getting compiled are constructed into
- // a real job. Packages which are *not* compiled still have their jobs
- // executed, but only if the work is fresh. This is to preserve their
- // artifacts if any exist.
- let job = if compiled {
- Job::new as fn(Work, Work) -> Job
- } else {
- Job::noop as fn(Work, Work) -> Job
- };
-
- if !compiled { jobs.ignore(pkg); }
-
if targets.is_empty() {
return Ok(())
}
try!(work.call(desc_tx.clone()));
dirty.call(desc_tx)
});
- dst.push((job(dirty, fresh), freshness));
+ dst.push((Job::new(dirty, fresh), freshness));
}
// If this is a custom build command, we need to not only build the
}
let (dirty, fresh, freshness) =
try!(custom_build::prepare(pkg, target, req, cx));
- run_custom.push((job(dirty, fresh), freshness));
+ run_custom.push((Job::new(dirty, fresh), freshness));
}
// If no build scripts were run, no need to compile the build script!